package com.yunhe.device.service.base.impl;

import com.alibaba.fastjson.JSON;
import com.github.stuxuhai.jpinyin.PinyinException;
import com.github.stuxuhai.jpinyin.PinyinHelper;
import com.yunhe.common.exception.ArgumentErrorException;
import com.yunhe.common.exception.ObjectNotFoundException;
import com.yunhe.common.exception.UniqueConstraintsException;
import com.yunhe.common.filter.ServerContextHolder;
import com.yunhe.common.model.ResultObject;
import com.yunhe.common.model.authority.RealStation;
import com.yunhe.common.util.CollectionUtil;
import com.yunhe.common.util.DateTimeUtils;
import com.yunhe.common.util.StringUtil;
import com.yunhe.device.client.AuthorityClient;
import com.yunhe.device.domain.base.DeviceType;
import com.yunhe.device.domain.device.Device;
import com.yunhe.device.model.base.*;
import com.yunhe.device.repository.base.EquipmentTypeRepository;
import com.yunhe.device.repository.base.impl.EquipmentTypeDao;
import com.yunhe.device.repository.device.EquipmentRepository;
import com.yunhe.device.service.base.AnlogTypeService;
import com.yunhe.device.service.base.EquipmentAttributeService;
import com.yunhe.device.service.base.EquipmentTypeService;
import com.yunhe.device.service.base.SerialNumService;
import com.yunhe.device.utils.BeansUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @ClassName EquipmentTypeServiceImpl
 * @Description TODO
 * @Author HeTao
 * @Date 2021/7/15 13:27
 * @Version 1.0
 **/
@Service
public class EquipmentTypeServiceImpl implements EquipmentTypeService {

    @Autowired
    private EquipmentTypeRepository equipmentTypeRepository;

    @Autowired
    private SerialNumService serialNumService;

    @Autowired
    private EquipmentTypeDao equipmentTypeDao;


    @Autowired
    private EquipmentAttributeService equipmentAttributeService;

    @Autowired
    private AnlogTypeService anlogTypeService;

    @Autowired
    private EquipmentRepository equipmentRepository;

    @Autowired
    private AuthorityClient authorityClient;

    @Override
    @Transactional(rollbackFor = Exception.class, transactionManager = "transactionManager")
    public DeviceType createEquipmentType(EquipmentTypeBo equipmentTypeBo) throws UniqueConstraintsException, ArgumentErrorException, PinyinException {
        DeviceType equipmentType = new DeviceType();
        BeanUtils.copyProperties(equipmentTypeBo,equipmentType);
        equipmentType.setId(null);
        String format = DateTimeUtils.format(DateTimeUtils.PATTERN.DATETIME.value(), new Date());
        equipmentType.setSn(DateTimeUtils.getTimestamp(format,null));
        equipmentType.setCreateTime(format);
        if(equipmentType.getType().equals("01")){
            equipmentType.setInitData(true);
            String type = serialNumService.generateSerialNumberByModelCode("TYPE");
            equipmentType.setName(type);
        }else {
            String projectCode = ServerContextHolder.getContext().getProjectCode();
            if(!StringUtil.isEmpty(projectCode)){
                equipmentType.setStationId(Long.valueOf(projectCode));
            }else {
                throw new ArgumentErrorException("请选择相关项目进行操作！");
            }
            String type = serialNumService.generateSerialNumberByModelCode("TY");
            equipmentType.setName(type);
        }
        processBeforeSave(equipmentType);
        DeviceType newEquipmentType = equipmentTypeRepository.save(equipmentType);
        //绑定设备属性以及点号类型
        //查询设备名称 设备位置 归属园区,设备sn码
        List<Long> ids = equipmentAttributeService.getEquipmentAttributesByName(Arrays.asList("equipLocation","ownedPark","equipName","equipSN"));
        if(!CollectionUtil.isEmpty(ids)){
            List<Long> equipAttrIds = equipmentTypeBo.getEquipAttrIds();
            if(CollectionUtil.isEmpty(equipAttrIds)){
                equipmentTypeBo.setEquipAttrIds(ids);
            }else {
                equipAttrIds.addAll(ids);
                equipmentTypeBo.setEquipAttrIds(equipAttrIds);
            }
        }
        if(!CollectionUtil.isEmpty(equipmentTypeBo.getEquipAttrIds())){
            equipmentTypeRepository.bindEquipAttr(newEquipmentType.getId(),equipmentTypeBo.getEquipAttrIds());
        }
        if(!CollectionUtil.isEmpty(equipmentTypeBo.getAnlogTypeIds())){
            equipmentTypeRepository.bindAnlogType(newEquipmentType.getId(),equipmentTypeBo.getAnlogTypeIds());
        }
        return newEquipmentType;
    }

    private void processBeforeSave(DeviceType equipmentType) throws ArgumentErrorException, UniqueConstraintsException, PinyinException {
        equipmentType.setPySn(PinyinHelper.getShortPinyin(equipmentType.getTitle()));
        //判断设备类型类型代码、编号、标题是否为空
        if (StringUtil.isEmpty(equipmentType.getName())
                || StringUtil.isEmpty(equipmentType.getTitle())) {
            throw new ArgumentErrorException("设备类型编码、标题不能为空");
        }
        //判断代码是否已存在
        DeviceType typeByName = this.findByName(equipmentType.getName());
        if (typeByName != null) {
            if (equipmentType.getId() == null || typeByName.getId().longValue() != equipmentType.getId().longValue()) {
                throw new UniqueConstraintsException("该设备类型编码已存在");
            }
        }
        if("01".equals(equipmentType.getType())){
            //判断编号是否已存在
            DeviceType typeByTitle = this.findByTitle(equipmentType.getTitle());
            if (typeByTitle != null) {
                if (equipmentType.getId() == null || typeByTitle.getId().longValue() != equipmentType.getId().longValue()) {
                    throw new UniqueConstraintsException("该设备类型名称已存在");
                }
            }
        }else {
            //判断编号是否已存在
            DeviceType typeByTitle = this.findByTitleAndStationId(equipmentType.getTitle(),equipmentType.getStationId());
            if (typeByTitle != null) {
                if (equipmentType.getId() == null || typeByTitle.getId().longValue() != equipmentType.getId().longValue()) {
                    throw new UniqueConstraintsException("该设备类型名称已存在");
                }
            }
        }
    }

    private DeviceType findByTitleAndStationId(String title, Long stationId) {
        return equipmentTypeRepository.findByTitleAndStationId(title,stationId);
    }

    private DeviceType findByTitle(String title) {
        return equipmentTypeRepository.findByTitle(title);
    }

    private DeviceType findByName(String name) {
        return equipmentTypeRepository.findByName(name);
    }

    @Override
    public Iterable<EquipmentTypeVo> getEquipmentTypeByCondition(EquipmentTypeQueryCondition equipmentTypeQueryCondition) {
        Iterable<EquipmentTypeVo> results = null;
        Page<DeviceType> equipmentTypes = null;
        Pageable pageable = PageRequest.of(equipmentTypeQueryCondition.getPage()-1, equipmentTypeQueryCondition.getSize());
        equipmentTypes = equipmentTypeDao.getEquipmentTypeByCondition(equipmentTypeQueryCondition);
        if(equipmentTypes != null){
            List<DeviceType> content = equipmentTypes.getContent();
            List<EquipmentTypeVo> equipmentTypeVos = BeansUtil.listCopy(content, EquipmentTypeVo.class);
            //查询设备类型关联的设备属性数以及点号类型数
            if(!CollectionUtil.isEmpty(equipmentTypeVos)){
                for (EquipmentTypeVo equipmentTypeVo : equipmentTypeVos) {
                    int equipAttrCount  = equipmentTypeRepository.getEquipAttrCountByEquipTypeId(equipmentTypeVo.getId());
                    //排除设备名称 设备位置  设备SN码 归属园区
                    if(equipAttrCount >= 4){
                        equipAttrCount = equipAttrCount-4;
                    }
                    int anlogTypeCount =  equipmentTypeRepository.getAnlogTypeCountByEquipTypeId(equipmentTypeVo.getId());
                    equipmentTypeVo.setEquipAttrCount(equipAttrCount);
                    equipmentTypeVo.setAnlogTypeCount(anlogTypeCount);
                }
            }
            results = new PageImpl(equipmentTypeVos,pageable,equipmentTypes.getTotalElements());
        }
        return results;
    }

    @Override
    public Iterable<EquipmentTypeVo> getFrontEquipmentTypeByCondition(EquipmentTypeQueryCondition equipmentTypeQueryCondition) throws ArgumentErrorException {
        Iterable<EquipmentTypeVo> results = null;
        Page<DeviceType> equipmentTypes = null;
        String projectCode = ServerContextHolder.getContext().getProjectCode();
        if(!StringUtil.isEmpty(projectCode)){
            equipmentTypeQueryCondition.setStationId(Long.valueOf(projectCode));
        }else {
            throw new ArgumentErrorException("请选择相关项目进行操作！");
        }
        List<Long> realStationIds = new ArrayList<>();
        ResponseEntity<ResultObject<Iterable<RealStation>>> responseEntity = authorityClient.findRealStationByStationId(Long.valueOf(projectCode));
        if(responseEntity != null && responseEntity.getStatusCode().is2xxSuccessful()){
            Object result = responseEntity.getBody().getResults();
            List<RealStation> realStations = JSON.parseArray(JSON.toJSONString(result), RealStation.class);
            for (RealStation realStation : realStations) {
                realStationIds.add(realStation.getId());
            }
        }
        Pageable pageable = PageRequest.of(equipmentTypeQueryCondition.getPage()-1, equipmentTypeQueryCondition.getSize());
        equipmentTypes = equipmentTypeDao.getFrontEquipmentTypeByCondition(equipmentTypeQueryCondition);
        if(equipmentTypes != null){
            List<DeviceType> content = equipmentTypes.getContent();
            List<EquipmentTypeVo> equipmentTypeVos = BeansUtil.listCopy(content, EquipmentTypeVo.class);
            //统计设备类型绑定设备数
            if(!CollectionUtil.isEmpty(equipmentTypeVos)){
                for (EquipmentTypeVo equipmentTypeVo : equipmentTypeVos) {
                    if(!CollectionUtil.isEmpty(realStationIds)){
                        int equipCount  = equipmentTypeRepository.getEquipCountByEquipTypeId(equipmentTypeVo.getId(),realStationIds);
                        equipmentTypeVo.setEquipCount(equipCount);
                    }
                }
            }
            results = new PageImpl(equipmentTypeVos,pageable,equipmentTypes.getTotalElements());
        }
        return results;
    }

    @Override
    public EquipmentTypeVo getEquipmentTypeById(Long id) throws ObjectNotFoundException {
        EquipmentTypeVo equipmentTypeVo = new EquipmentTypeVo();
        DeviceType equipmentType = equipmentTypeRepository.findById(id).orElse(null);
        if(equipmentType == null){
            throw new ObjectNotFoundException("查无次设备类型信息");
        }
        BeanUtils.copyProperties(equipmentType,equipmentTypeVo);
        //查询当前设备锁勾选的属性
        List<EquipmentAttributesVo> equipmentAttributesVos = equipmentAttributeService.getEquipmentAttributesByEquipTypeId(id);
        if(!CollectionUtil.isEmpty(equipmentAttributesVos)){
            List<String> names = Arrays.asList("equipLocation","ownedPark","equipName","equipSN");
            List<EquipmentAttributesVo> equipmentAttributesVoList = equipmentAttributesVos.stream().filter(equipAttrValueVo -> {
                return !names.contains(equipAttrValueVo.getName());
            }).collect(Collectors.toList());
            if(!CollectionUtil.isEmpty(equipmentAttributesVoList)){
                equipmentTypeVo.setEquipmentAttributesVos(equipmentAttributesVoList);
                List<Long> collect = equipmentAttributesVoList.stream().map(EquipmentAttributesVo::getId).collect(Collectors.toList());
                equipmentTypeVo.setEquipAttrIds(collect);
            }
        }
        List<AnlogTypeVo> anlogTypeVos = anlogTypeService.getAnlogTypeByEquipTypeId(id);
        if(!CollectionUtil.isEmpty(anlogTypeVos)){
            equipmentTypeVo.setAnlogTypeVos(anlogTypeVos);
            List<Long> collect = anlogTypeVos.stream().map(AnlogTypeVo::getId).collect(Collectors.toList());
            equipmentTypeVo.setAnlogTypeIds(collect);
        }
        return equipmentTypeVo;
    }

    @Override
    @Transactional(rollbackFor = Exception.class, transactionManager = "transactionManager")
    public void deleteEquipmentTypeById(Long id) throws ObjectNotFoundException, ArgumentErrorException {
        DeviceType equipmentType = equipmentTypeRepository.findById(id).orElse(null);
        if(equipmentType ==  null){
            throw new ObjectNotFoundException("查无次设备类型信息");
        }
        List<Device> equipmentList = equipmentTypeRepository.getEquipByEquipTypeId(equipmentType.getId());
        if(!CollectionUtil.isEmpty(equipmentList)){
            throw new ArgumentErrorException("设备类型："+equipmentType.getTitle()+"已与相关设备绑定，不能删除！");
        }
        //先与设备属性以及点号类型解绑 后删除
        equipmentTypeRepository.unbindEquipAttr(id);
        equipmentTypeRepository.unbindAnlogType(id);
        equipmentTypeRepository.deleteById(id);
    }
    @Override
    @Transactional(rollbackFor = Exception.class, transactionManager = "transactionManager")
    public void deleteFrontEquipmentTypeById(Long id) throws ObjectNotFoundException, ArgumentErrorException {
        DeviceType equipmentType = equipmentTypeRepository.findById(id).orElse(null);
        if(equipmentType ==  null){
            throw new ObjectNotFoundException("查无次设备类型信息");
        }
        if(equipmentType.isInitData()){
            throw new ArgumentErrorException("当前设备类型为后端初始化设备类型不能删除");
        }
        //先解绑设备属性以及点号类型
        equipmentTypeRepository.unbindEquipAttr(id);
        equipmentTypeRepository.unbindAnlogType(id);
        List<Device> devices = equipmentTypeRepository.getEquipByEquipTypeId(equipmentType.getId());
        if(!CollectionUtil.isEmpty(devices)){
            for (Device device : devices) {
                equipmentRepository.unbindOffice(device.getId());
                equipmentTypeRepository.unbindCustEquipAttrAndEquip(device.getId());
                equipmentTypeRepository.unbindEquipAndAnlogType(device.getId());
            }
        }
        equipmentTypeRepository.unbindEquipAttrAndEquip(id);
        equipmentTypeRepository.deleteEquipByEquipTypeId(id);
        equipmentTypeRepository.deleteById(id);
    }

    @Override
    @Transactional(rollbackFor = Exception.class, transactionManager = "transactionManager")
    public DeviceType updateEquipmentType(EquipmentTypeBo equipmentTypeBo) throws ObjectNotFoundException, UniqueConstraintsException, ArgumentErrorException, PinyinException {
        DeviceType equipmentTypeById = equipmentTypeRepository.findById(equipmentTypeBo.getId()).orElse(null);
        if(equipmentTypeById == null){
            throw new ObjectNotFoundException("找不到对应设备类型信息");
        }
        equipmentTypeById.setUpdateTime(DateTimeUtils.format(DateTimeUtils.PATTERN.DATETIME.value(), new Date()));
        equipmentTypeById.setPhoto(equipmentTypeBo.getPhoto());
        equipmentTypeById.setTitle(equipmentTypeBo.getTitle());
        processBeforeSave(equipmentTypeById);
        DeviceType newEquipmentType = equipmentTypeRepository.save(equipmentTypeById);
        //先与设备属性以及点号类型解绑 后删除
        equipmentTypeRepository.unbindEquipAttr(newEquipmentType.getId());
        equipmentTypeRepository.unbindAnlogType(newEquipmentType.getId());
        //绑定设备属性以及点号类型
        List<Long> ids = equipmentAttributeService.getEquipmentAttributesByName(Arrays.asList("equipLocation","ownedPark","equipName","equipSN"));
        if(!CollectionUtil.isEmpty(ids)){
            List<Long> equipAttrIds = equipmentTypeBo.getEquipAttrIds();
            if(CollectionUtil.isEmpty(equipAttrIds)){
                equipmentTypeBo.setEquipAttrIds(ids);
            }else {
                equipAttrIds.addAll(ids);
                equipmentTypeBo.setEquipAttrIds(equipAttrIds);
            }
        }
        if(!CollectionUtil.isEmpty(equipmentTypeBo.getEquipAttrIds())){
            equipmentTypeRepository.bindEquipAttr(newEquipmentType.getId(),equipmentTypeBo.getEquipAttrIds());
        }
        if(!CollectionUtil.isEmpty(equipmentTypeBo.getAnlogTypeIds())){
            equipmentTypeRepository.bindAnlogType(newEquipmentType.getId(),equipmentTypeBo.getAnlogTypeIds());
        }
        return newEquipmentType;
    }

    @Override
    @Transactional(rollbackFor = Exception.class, transactionManager = "transactionManager")
    public DeviceType updateFrontEquipmentType(EquipmentTypeBo equipmentTypeBo) throws ObjectNotFoundException, ArgumentErrorException, UniqueConstraintsException, PinyinException {
        DeviceType equipmentTypeById = equipmentTypeRepository.findById(equipmentTypeBo.getId()).orElse(null);
        if(equipmentTypeById == null){
            throw new ObjectNotFoundException("找不到对应设备类型信息");
        }
        if(equipmentTypeById.isInitData()){
            throw new ArgumentErrorException("当前设备类型为后端初始化设备类型不能编辑");
        }
        equipmentTypeById.setUpdateTime(DateTimeUtils.format(DateTimeUtils.PATTERN.DATETIME.value(), new Date()));
        equipmentTypeById.setPhoto(equipmentTypeBo.getPhoto());
        equipmentTypeById.setTitle(equipmentTypeBo.getTitle());
        processBeforeSave(equipmentTypeById);
        DeviceType newEquipmentType = equipmentTypeRepository.save(equipmentTypeById);
        //先与设备属性以及点号类型解绑 后删除
        equipmentTypeRepository.unbindEquipAttr(newEquipmentType.getId());
        equipmentTypeRepository.unbindAnlogType(newEquipmentType.getId());
        //绑定设备属性以及点号类型
        List<Long> ids = equipmentAttributeService.getEquipmentAttributesByName(Arrays.asList("equipLocation","ownedPark","equipName","equipSN"));
        if(!CollectionUtil.isEmpty(ids)){
            List<Long> equipAttrIds = equipmentTypeBo.getEquipAttrIds();
            if(CollectionUtil.isEmpty(equipAttrIds)){
                equipmentTypeBo.setEquipAttrIds(ids);
            }else {
                equipAttrIds.addAll(ids);
                equipmentTypeBo.setEquipAttrIds(equipAttrIds);
            }
        }
        if(!CollectionUtil.isEmpty(equipmentTypeBo.getEquipAttrIds())){
            equipmentTypeRepository.bindEquipAttr(newEquipmentType.getId(),equipmentTypeBo.getEquipAttrIds());
        }
        if(!CollectionUtil.isEmpty(equipmentTypeBo.getAnlogTypeIds())){
            equipmentTypeRepository.bindAnlogType(newEquipmentType.getId(),equipmentTypeBo.getAnlogTypeIds());
        }
        return newEquipmentType;
    }

    @Override
    @Transactional(rollbackFor = Exception.class, transactionManager = "transactionManager")
    public void updateEquipmentTypeStauts(StatusVo statusVo) throws ObjectNotFoundException {
        List<Long> ids = statusVo.getIds();
        for (Long id : ids) {
            DeviceType equipmentTypeById = equipmentTypeRepository.findById(id).orElse(null);
            if(equipmentTypeById == null){
                throw new ObjectNotFoundException("找不到对应设备类型信息");
            }
            equipmentTypeById.setUpdateTime(DateTimeUtils.format(DateTimeUtils.PATTERN.DATETIME.value(), new Date()));
            equipmentTypeById.setActivity(statusVo.getActivity());
            DeviceType newEquipmentType = equipmentTypeRepository.save(equipmentTypeById);
        }
    }


    @Override
    public Iterable<AnlogTypeVo> getAnlogTypeById(Long id, int page, int size) {
        return anlogTypeService.getAnlogTypeByEquipTypeId(id,page,size);
    }

    @Override
    public List<DeviceType> getEquipmentType() throws ArgumentErrorException {
        String projectCode = ServerContextHolder.getContext().getProjectCode();
        if(!StringUtil.isEmpty(projectCode)){
            return equipmentTypeRepository.findByStationId(Long.valueOf(projectCode));
        }else {
            throw new ArgumentErrorException("请选择相关项目进行操作！");
        }
    }
}
